package com.abc.pay.client;

import lombok.extern.slf4j.Slf4j;

import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.net.InetAddress;
import java.net.Socket;
import java.nio.charset.StandardCharsets;
import java.security.Signature;
import java.security.cert.Certificate;

@Slf4j
public class SignService {
    private static final String SIGNATURE_ALGORITHM = "SHA1withRSA";
    private static SignService uniqueInstanceOf_SignService = null;
    private static Certificate cert = null;
    private static MerchantPara para = null;

    private static synchronized void syncInit() throws TrxException {
        if (uniqueInstanceOf_SignService == null) {
            uniqueInstanceOf_SignService = new SignService();
        }
    }

    public static SignService getUniqueInstance() throws TrxException {
        if (uniqueInstanceOf_SignService == null) {
            syncInit();
        }
        return uniqueInstanceOf_SignService;
    }

    private SignService() throws TrxException {
        try {
            para = MerchantConfig.getUniqueInstance().getPara();
            cert = para.getTrustpayCertificate();
        } catch (TrxException var2) {
            throw new TrxException(var2.getCode(), var2.getMessage());
        }
    }

    public String signMessage(int i, String aMessage) throws TrxException {
        String tMessage;
        try {
            tMessage = this.fileSignMessage(i, aMessage);
        } catch (TrxException var5) {
            throw var5;
        } catch (Exception var6) {
            throw new TrxException("1102", "签名交易报文时发生错误 - " + var6.getMessage());
        }
        return tMessage;
    }

    private String fileSignMessage(int i, String aMessage) throws Exception {
        Signature tSignature;
        String tMessage;
        try {
            tSignature = Signature.getInstance(SIGNATURE_ALGORITHM);
            tSignature.initSign(para.getMerchantKey(i));
            tSignature.update(aMessage.getBytes(StandardCharsets.UTF_8));
            byte[] tSigned = tSignature.sign();
            Base64 tBase64 = new Base64();
            String tSignedBase64 = tBase64.encode(tSigned);
            tMessage = "{\"Message\":" + aMessage + ",\"Signature-Algorithm\":\"" + SIGNATURE_ALGORITHM + "\",\"Signature\":\"" + tSignedBase64 + "\"}";
        } catch (Exception e) {
            log.error(e.getMessage());
            throw e;
        }
        return tMessage;
    }

    private String signServerSignMessage(String aMessage) throws Exception {
        String tMessage;
        Socket tSocket = null;
        OutputStream tOut = null;
        BufferedReader tIn = null;
        String tSignServerIP = para.getSignServerIP();
        int tSignServerPort = Integer.parseInt(para.getSignServerPort());
        String tSignServerPass = para.getSignServerPassword();
        try {
            tSocket = new Socket(InetAddress.getByName(tSignServerIP), tSignServerPort);
            Base64 tBase64 = new Base64();
            String tData = tBase64.encode(aMessage.getBytes(StandardCharsets.UTF_8));
            StringBuffer tSignRequest = (new StringBuffer()).append("<SignReq>").append("<Password>").append(tSignServerPass).append("</Password>").append("<Signature-Algorithm>").append(SIGNATURE_ALGORITHM).append("</Signature-Algorithm>").append("<Data>").append(tData).append("</Data>").append("</SignReq>\n");
            tOut = tSocket.getOutputStream();
            tOut.write(tSignRequest.toString().getBytes("iso8859-1"));
            tOut.flush();
            tIn = new BufferedReader(new InputStreamReader(tSocket.getInputStream()));
            String tLine = tIn.readLine();
            if (tLine == null) {
                throw new TrxException("1104", "签名服务器返回签名错误", "无响应");
            }
            XMLDocument tSignedResponse = new XMLDocument(tLine);
            String tSignBase64;
            if (!tSignedResponse.getValueNoNull("RC").equals("0")) {
                throw new TrxException("1104", "签名服务器返回签名错误", "错误代码[" + tSignedResponse.getValueNoNull("RC") + "]");
            }
            tSignBase64 = tSignedResponse.getValueNoNull("Signature");
            tMessage = "{\"Message\":" + aMessage + ",\"Signature-Algorithm\":\"" + SIGNATURE_ALGORITHM + "\",\"Signature\":\"" + tSignBase64 + "\"}";
        } catch (TrxException var29) {
            throw var29;
        } catch (Exception var30) {
            throw new TrxException("1103", "无法连线签名服务器", var30.getMessage());
        } finally {
            if (tIn != null) {
                try {
                    tIn.close();
                } catch (Exception e) {
                    log.error(e.getMessage());
                }
            }
            if (tOut != null) {
                try {
                    tOut.close();
                } catch (Exception e) {
                    log.error(e.getMessage());
                }
            }
            if (tSocket != null) {
                try {
                    tSocket.close();
                } catch (Exception e) {
                    log.error(e.getMessage());
                }
            }
        }
        return tMessage;
    }

    public XMLDocument signMessageXML(int i, XMLDocument aMessage) throws Exception {
        StringBuffer tMessage = new StringBuffer();
        Signature tSignature;
        try {
            tSignature = Signature.getInstance(SIGNATURE_ALGORITHM);
            tSignature.initSign(para.getMerchantKey(i));
            tSignature.update(aMessage.toString().getBytes(StandardCharsets.UTF_8));
            byte[] tSigned = tSignature.sign();
            Base64 tBase64 = new Base64();
            String tSignedBase64 = tBase64.encode(tSigned);
            tMessage.append("<Message>").append(aMessage).append("</Message>").append("<Signature-Algorithm>").append(SIGNATURE_ALGORITHM).append("</Signature-Algorithm>").append("<Signature>").append(tSignedBase64).append("</Signature>");
        } catch (Exception e) {
            log.error(e.getMessage());
            throw e;
        }
        return new XMLDocument(tMessage.toString());
    }

    public static void verifySign(JSON json, String aMessage) throws TrxException {
        String tTrxResponse = json.GetKeyValue("Message");
        if (tTrxResponse == null) {
            throw new TrxException("1301", "线上支付平台的响应报文不完整", "无[Message]段！");
        } else {
            String tAlgorithm = json.GetKeyValue("Signature-Algorithm");
            if (tAlgorithm == null) {
                throw new TrxException("1301", "线上支付平台的响应报文不完整", "无[Signature-Algorithm]段！");
            } else {
                String tSignBase64 = json.GetKeyValue("Signature");
                if (tSignBase64 == null) {
                    throw new TrxException("1301", "线上支付平台的响应报文不完整", "无[Signature]段！");
                } else {
                    Base64 tBase64 = new Base64();
                    byte[] tSign = tBase64.decode(tSignBase64);
                    try {
                        Signature tSignature = Signature.getInstance(tAlgorithm);
                        tSignature.initVerify(para.getTrustpayCertificate());
                        tSignature.update(tTrxResponse.getBytes("GBK"));
                        if (!tSignature.verify(tSign)) {
                            throw new TrxException("1302", "线上支付平台的响应报文签名验证失败");
                        }
                    } catch (TrxException var8) {
                        throw var8;
                    } catch (Exception var9) {
                        var9.printStackTrace(System.out);
                        throw new TrxException("1302", "线上支付平台的响应报文签名验证失败 - " + var9.getMessage());
                    }
                }
            }
        }
    }

    public XMLDocument verifySignXML(XMLDocument aMessage) throws TrxException {
        XMLDocument tTrxResponse = aMessage.getValue("Message");
        if (tTrxResponse == null) {
            throw new TrxException("1301", "线上支付平台的响应报文不完整", "无[Message]段！");
        } else {
            XMLDocument tAlgorithm = aMessage.getValue("Signature-Algorithm");
            if (tAlgorithm == null) {
                throw new TrxException("1301", "线上支付平台的响应报文不完整", "无[Signature-Algorithm]段！");
            } else {
                XMLDocument tSignBase64 = aMessage.getValue("Signature");
                if (tSignBase64 == null) {
                    throw new TrxException("1301", "线上支付平台的响应报文不完整", "无[Signature]段！");
                } else {
                    Base64 tBase64 = new Base64();
                    byte[] tSign = tBase64.decode(tSignBase64.toString());

                    try {
                        Signature tSignature = Signature.getInstance(tAlgorithm.toString());
                        tSignature.initVerify(para.getTrustpayCertificate());
                        tSignature.update(tTrxResponse.toString().getBytes("gbk"));
                        boolean result = tSignature.verify(tSign);
                        if (!result) {
                            throw new TrxException("1302", "线上支付平台的响应报文签名验证失败");
                        } else {
                            return tTrxResponse;
                        }
                    } catch (TrxException var9) {
                        throw var9;
                    } catch (Exception var10) {
                        var10.printStackTrace(System.out);
                        throw new TrxException("1302", "线上支付平台的响应报文签名验证失败 - " + var10.getMessage());
                    }
                }
            }
        }
    }
}

